import os

from werkzeug.contrib.cache import SimpleCache, FileSystemCache

from bopress.utils import Utils
from bopress import settings


class GroupSimpleCache(SimpleCache):
    _paths = set()

    def __init__(self, threshold=500, default_timeout=300):
        SimpleCache.__init__(self, threshold, default_timeout)

    def set(self, path=list(), value=None, timeout=None):
        if not path:
            return
        if len(path) == 0:
            return
        key = "/".join(path)
        self._paths.add(key)
        super(GroupSimpleCache, self).set(key, value, timeout)

    def get(self, path=list()):
        key = "/".join(path)
        return super(GroupSimpleCache, self).get(key)

    def get_many(self, path=list()):
        prefix = "/".join(path)
        cache_items = dict()
        for key in self._paths:
            if key.startswith(prefix):
                cache_items[key] = super(GroupSimpleCache, self).get(key)
        return cache_items

    def add(self, path=list(), value=None, timeout=None):
        if not path:
            return
        if len(path) == 0:
            return
        key = "/".join(path)
        self._paths.add(key)
        super(GroupSimpleCache, self).add(key, value, timeout)

    def delete(self, path=list()):
        prefix = "/".join(path)
        for key in self._paths:
            if key.startswith(prefix):
                super(GroupSimpleCache, self).delete(key)


class GroupFileCache(FileSystemCache):
    _paths = set()

    def __init__(self, cache_dir, threshold=500, default_timeout=300,
                 mode=0o600):
        FileSystemCache.__init__(self, cache_dir, threshold, default_timeout, mode)

    def set(self, path=list(), value=None, timeout=None):
        if not path:
            return
        if len(path) == 0:
            return
        key = "/".join(path)
        self._paths.add(key)
        super(GroupFileCache, self).set(key, value, timeout)

    def get(self, path=list()):
        key = "/".join(path)
        return super(GroupFileCache, self).get(key)

    def get_many(self, path=list()):
        prefix = "/".join(path)
        cache_items = dict()
        for key in self._paths:
            if key.startswith(prefix):
                cache_items[key] = super(GroupFileCache, self).get(key)
        return cache_items

    def add(self, path=list(), value=None, timeout=None):
        if not path:
            return
        if len(path) == 0:
            return
        key = "/".join(path)
        self._paths.add(key)
        super(GroupFileCache, self).add(key, value, timeout)

    def delete(self, path=list()):
        prefix = "/".join(path)
        for key in self._paths:
            if key.startswith(prefix):
                super(GroupFileCache, self).delete(key)


class Cache(object):
    # file = type("file", (), {})
    # mem = type("mem", (), {})
    __instance__ = None

    @staticmethod
    def default():
        if Cache.__instance__:
            return Cache.__instance__
        if settings.CACHE_MODE == "simple":
            Cache.__instance__ = GroupSimpleCache()
            return Cache.__instance__
        elif settings.CACHE_MODE == "file":
            path = Utils.mkdirs(os.path.join(settings.BASE_DIR, "cache"))
            Cache.__instance__ = GroupFileCache(path)
            return Cache.__instance__
        return None
